home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 1.iso / ARGONET / PD / FILER / X-FILES.ZIP / 057 / !X-Files / c / x-check < prev   
Text File  |  1996-03-27  |  6KB  |  244 lines

  1. /* x-check.c */
  2.  
  3. #include "kernel.h"
  4. #include <stdio.h>
  5. #include <ctype.h>
  6. #include "swis.h"
  7. #include <stdarg.h>
  8. #include <setjmp.h>
  9.  
  10. #include "chunks.h"
  11.  
  12. #define FREE 0x45455246
  13.  
  14. static jmp_buf jb;
  15.  
  16. static void ASSERT(int t)
  17. {
  18.    static _kernel_oserror assertFailed = { 0, "Assert failed" };
  19.  
  20.    if (!t)
  21.       e(&assertFailed);
  22. }
  23.  
  24. static void e(_kernel_oserror *err)
  25. {
  26.    if (err)
  27.       longjmp(jb, (int) err);
  28. }
  29.  
  30. static int power2(int x)
  31. {
  32.    while (x && !(x & 1)) x >>= 1;
  33.    return x == 1;
  34. }
  35.  
  36. static void test(int c, const char *fmt, ...)
  37. {
  38.    va_list ap;
  39.    va_start(ap, fmt);
  40.  
  41.    if (!c)
  42.    {
  43.       char buffer[256];
  44.       vsprintf(buffer, fmt, ap);
  45.       printf("x-check: %s\n", buffer);
  46.    }
  47.  
  48.    va_end(ap);
  49. }
  50.  
  51. static int okOffset(xFiles_info *pInfo, unsigned offset)
  52. {
  53.    return (offset & (pInfo->fileHeader.allocationSize - 1)) == 0;
  54. }
  55.  
  56. static void testChunk(xFiles_info *pInfo, unsigned cnkNum, xFiles_chunk *pChunk)
  57. {
  58.    unsigned maxChunk;
  59.  
  60.    test(pInfo->fileHeader.chunkTable.size % sizeof(xFiles_chunk) == 0,
  61.         "Bad size for chunk table %d",
  62.         pInfo->fileHeader.chunkTable.size);
  63.  
  64.    maxChunk = pInfo->fileHeader.chunkTable.size / sizeof(xFiles_chunk);
  65.  
  66.    test(cnkNum < maxChunk, "Bad chunk number %d", cnkNum);
  67.  
  68.    if (pChunk->usage == FREE)
  69.    {
  70.       test(pChunk->offset < maxChunk,
  71.            "Chunk %d (free) bad offset %08x", cnkNum, pChunk->offset);
  72.  
  73.       test(pChunk->size == FREE,
  74.            "Chunk %d (free) size is %08x (should be %08x)",
  75.            cnkNum, pChunk->size, FREE);
  76.  
  77.       test(pChunk->allocSize == FREE,
  78.            "Chunk %d (free) allocSize is %08x (should be %08x)",
  79.            cnkNum, pChunk->allocSize, FREE);
  80.    }
  81.    else
  82.    {
  83.       test(okOffset(pChunk->offset),
  84.            "Chunk %d (used) bad offset %08x", cnkNum, pChunk->offset);
  85.       test(pChunk->size <= pChunk->allocSize)
  86.            "Chunk %d (used) bad size %08x (allocSize %08x)",
  87.            cnkNum, pChunk->size, pChunk->allocSize);
  88.       test(okOffset(pChunk->allocSize),
  89.            "Chunk %d (used) bad allocSize %08x", cnkNum, pChunk->allocSize);
  90.    }
  91. }
  92.  
  93. static int chcmp(const void *a, const void *b)
  94. {
  95.    const xFiles_chunk *ca = a;
  96.    const xFiles_chunk *cb = b;
  97.  
  98.    return (int) ca->offset - (int) cb->offset;
  99. }
  100.  
  101. static void checkChunkTable(xFiles_info *pInfo)
  102. {
  103.    xFiles_chunk *ct;
  104.    unsigned maxChunk, freeChunk;
  105.    unsigned i, j;
  106.  
  107.    maxChunk = pInfo->fileHeader.chunkTable.size / sizeof(xFiles_chunk);
  108.  
  109.    ct = malloc(maxChunk * sizeof(xFiles_chunk));
  110.    ASSERT(ct != NULL);
  111.  
  112.    e(xFiles_readChunk(pInfo, ct, 0, maxChunk * sizeof(xFiles_chunk), 0));
  113.  
  114.    /* First follow the free chain */
  115.  
  116.    freeChunk = pInfo->fileHeader.freeChunk;
  117.  
  118.    while (freeChunk != 0)
  119.    {
  120.       testChunk(pInfo, freeChunk, &ct[freeChunk]);
  121.       ct[freeChunk].usage = 0;
  122.       freeChunk = ct[freeChunk].offset;
  123.    }
  124.  
  125.    /* Scan for any untouched free chunks and also discard any free chunks ready
  126.     * for checking the used ones.
  127.     */   
  128.  
  129.    for (i = 0, j = 0; i < maxChunk; i++)
  130.    {
  131.       if (ct[i].usage == FREE)
  132.       {
  133.          printf("x-check: free chunk %d is unlinked\n", c);
  134.       }
  135.  
  136.       if (ct[i].size != free)
  137.          ct[j++] = ct[i];
  138.    }
  139.  
  140.    maxChunk = j;
  141.  
  142.    /* Now sort the array on offset so we can look for overlaps */
  143.  
  144.    qsort(ct, maxChunk, sizeof(xFiles_chunk), chcmp);
  145.  
  146.    free(ct);
  147. }
  148.  
  149. static _kernel_oserror *check(const char *fileName, int fix)
  150. {
  151.    xFiles_info info;
  152.    _kernel_swi_regs regs;
  153.    _kernel_oserror *err;
  154.    unsigned fileSize;
  155.  
  156.    regs.r[0] = 0x4F;
  157.    regs.r[1] = (int) fileName;
  158.    if (err = _kernel_swi(OS_Find, ®s, ®s), err)
  159.       return err;
  160.  
  161.    info.FileHandle = regs.r[0];
  162.  
  163.    if (err = xFiles_openImage(&info), err)
  164.       goto fail;
  165.  
  166.    if (err = xFiles_getLength(&info, &fileSize), err)
  167.       goto fail;
  168.  
  169.    if (err = (_kernel_oserror *) setjmp(jb), err)
  170.       goto fail;
  171.  
  172.    /* Validate the header */
  173.  
  174.    test(info.fileHeader.hdrSize == sizeof(xFiles_header),
  175.         "Illegal hdrSize %d",
  176.         info.fileHeader.hdrSize);
  177.  
  178.    test(info.fileHeader.structureVersion == xFiles_STRUCTUREVERSION,
  179.         "Illegal structureVersion %d",
  180.         info.fileHeader.structureVersion);
  181.  
  182.    test(info.fileHeader.directoryVersion == xFiles_DIRECTORYVERSION,
  183.         "Illegal directoryVersion %d",
  184.         info.fileHeader.directoryVersion);
  185.  
  186.    testChunk(&info, 0, &info.fileHeader.chunkTable);
  187.  
  188.    test(power2(info.fileHeader.allocationUnit),
  189.         "Illegal allocationUnit %d",
  190.         info.fileHeader.allocationUnit);
  191.  
  192.    testChunkTable(&info);
  193.    test(info.fileHeader.waste < fileSize,
  194.         "Illegal waste %d (fileSize is %d)",
  195.         info.fileHeader.waste, fileSize);
  196.  
  197.    testStructure(&info);     
  198.  
  199.    if (err = xFiles_FlushFileInfo(&info), err)
  200.       goto fail;
  201.  
  202.    regs.r[0] = 0;
  203.    regs.r[1] = info.fileHandle;
  204.    return _kernel_swi(OS_Find, ®s, ®s);
  205.  
  206. fail:
  207.    regs.r[0] = 0;
  208.    regs.r[1] = info.fileHandle;
  209.    (void) _kernel_swi(OS_Find, ®s, ®s);
  210.    return err;
  211. }
  212.  
  213. int main(int argc, char *argv[])
  214. {
  215.    int argn;
  216.    int fix = 0;
  217.  
  218.    for (argn = 1; argn < argc; argn++)
  219.    {
  220.       if (*argv[argn] == '-')
  221.       {
  222.          switch (tolower(argv[argn][1]))
  223.          {
  224.             case 'f':
  225.                fix = 1;
  226.                break;
  227.             default:
  228.                fprintf(stderr, "Ignoring unknown option \"%s\"\n", argv[argn]);
  229.                break;
  230.          }
  231.       }
  232.    }
  233.  
  234.    for (argn = 1; argn < argc; argn++)
  235.    {
  236.       if (*argv[argn] != '-')
  237.       {
  238.          check(argv[argn], fix);
  239.       }
  240.    }
  241.  
  242.    return 0;
  243. }
  244.